package com.hd123.rumba.util;

import java.io.*;
import java.util.*;

public class ConHashMap extends AbstractMap implements Map, Cloneable,
		Serializable {
	private static class Entry implements java.util.Map.Entry {

		int hash;

		Object key;

		Object value;

		Entry next;

		protected Object clone() {
			return new Entry(hash, key, value, next == null ? null
					: (Entry) next.clone());
		}

		public Object getKey() {
			return key;
		}

		public Object getValue() {
			return value;
		}

		public Object setValue(Object obj) {
			Object obj1 = value;
			value = obj;
			return obj1;
		}

		public boolean equals(Object obj) {
			if (!(obj instanceof java.util.Map.Entry)) {
				return false;
			} else {
				java.util.Map.Entry entry = (java.util.Map.Entry) obj;
				return (key == null ? entry.getKey() == null : key.equals(entry
						.getKey()))
						&& (value == null ? entry.getValue() == null : value
								.equals(entry.getValue()));
			}
		}

		public int hashCode() {
			return hash ^ (value == null ? 0 : value.hashCode());
		}

		public String toString() {
			return key.toString() + "=" + value.toString();
		}

		Entry(int i, Object obj, Object obj1, Entry entry) {
			hash = i;
			key = obj;
			value = obj1;
			next = entry;
		}
	}

	private class HashIterator implements Iterator {

		ConHashMap.Entry table[];

		int index;

		ConHashMap.Entry entry;

		ConHashMap.Entry lastReturned;

		int type;

		public boolean hasNext() {
			if (entry != null) {
				return true;
			}
			while (index-- > 0) {
				if ((entry = table[index]) != null) {
					return true;
				}
			}
			return false;
		}

		public Object next() {
			if (entry == null) {
				while (index-- > 0 && (entry = table[index]) == null)
					;
			}
			if (entry != null) {
				ConHashMap.Entry entry1 = lastReturned = entry;
				entry = entry1.next;
				if (type == 0) {
					return entry1.key;
				}
				if (type == 1) {
					return entry1.value;
				} else {
					return entry1;
				}
			} else {
				throw new NoSuchElementException();
			}
		}

		public void remove() {
			if (lastReturned == null) {
				throw new IllegalStateException();
			}
			synchronized (ConHashMap.this) {
				ConHashMap.Entry aentry[] = ConHashMap.this.table;
				int i = (lastReturned.hash & 0x7fffffff) % aentry.length;
				ConHashMap.Entry entry1 = aentry[i];
				ConHashMap.Entry entry2 = null;
				for (; entry1 != null; entry1 = entry1.next) {
					if (entry1 == lastReturned) {
						if (entry2 == null) {
							aentry[i] = entry1.next;
						} else {
							entry2.next = entry1.next;
						}
						count--;
						lastReturned = null;
						return;
					}
					entry2 = entry1;
				}

				throw new InternalError("Iterated off table when doing remove");
			}
		}

		HashIterator(int i) {
			table = ConHashMap.this.table;
			index = table.length;
			type = i;
		}
	}

//	private static final int KEYS = 0;

//	private static final int VALUES = 1;

//	private static final int ENTRIES = 2;

	private transient Entry table[];

	private transient int count;

	private int threshold;

	private float loadFactor;

	private transient Set keySet;

	private transient Set entrySet;

	private transient Collection values;

	public int size() {
		return count;
	}

	public boolean isEmpty() {
		return count == 0;
	}

	public boolean containsValue(Object obj) {
		Entry aentry[] = table;
		if (obj == null) {
			for (int i = aentry.length; i-- > 0;) {
				for (Entry entry = aentry[i]; entry != null; entry = entry.next) {
					if (entry.value == null) {
						return true;
					}
				}

			}

		} else {
			for (int j = aentry.length; j-- > 0;) {
				for (Entry entry1 = aentry[j]; entry1 != null; entry1 = entry1.next) {
					if (obj.equals(entry1.value)) {
						return true;
					}
				}

			}

		}
		return false;
	}

	public boolean containsKey(Object obj) {
		Entry aentry[] = table;
		if (obj != null) {
			int i = obj.hashCode();
			int j = (i & 0x7fffffff) % aentry.length;
			for (Entry entry1 = aentry[j]; entry1 != null; entry1 = entry1.next) {
				if (entry1.hash == i && entry1.key.equals(obj)) {
					return true;
				}
			}

		} else {
			for (Entry entry = aentry[0]; entry != null; entry = entry.next) {
				if (entry.key == null) {
					return true;
				}
			}

		}
		return false;
	}

	public Object get(Object obj) {
		Entry aentry[] = table;
		if (obj != null) {
			int i = obj.hashCode();
			int j = (i & 0x7fffffff) % aentry.length;
			for (Entry entry1 = aentry[j]; entry1 != null; entry1 = entry1.next) {
				if (entry1.hash == i && entry1.key.equals(obj)) {
					return entry1.value;
				}
			}

		} else {
			for (Entry entry = aentry[0]; entry != null; entry = entry.next) {
				if (entry.key == null) {
					return entry.value;
				}
			}

		}
		return null;
	}

	private void rehash() {
		int i = table.length;
		int j = i * 2 + 1;
		Entry aentry[] = table;
		Entry aentry1[] = new Entry[j];
		for (int k = i; k-- > 0;) {
			for (Entry entry = aentry[k]; entry != null;) {
				Entry entry1 = (Entry) entry.clone();
				entry = entry.next;
				int l = (entry1.hash & 0x7fffffff) % j;
				entry1.next = aentry1[l];
				aentry1[l] = entry1;
			}

		}

		threshold = (int) ((float) j * loadFactor);
		table = aentry1;
	}

	public synchronized Object put(Object obj, Object obj1) {
		Entry aentry[] = table;
		int i = 0;
		int j = 0;
		if (obj != null) {
			i = obj.hashCode();
			j = (i & 0x7fffffff) % aentry.length;
			for (Entry entry = aentry[j]; entry != null; entry = entry.next) {
				if (entry.hash == i && entry.key.equals(obj)) {
					Object obj2 = entry.value;
					entry.value = obj1;
					return obj2;
				}
			}

		} else {
			for (Entry entry1 = aentry[0]; entry1 != null; entry1 = entry1.next) {
				if (entry1.key == null) {
					Object obj3 = entry1.value;
					entry1.value = obj1;
					return obj3;
				}
			}

		}
		if (count >= threshold) {
			rehash();
			aentry = table;
			j = (i & 0x7fffffff) % aentry.length;
		}
		aentry[j] = new Entry(i, obj, obj1, aentry[j]);
		count++;
		return null;
	}

	public synchronized Object remove(Object obj) {
		Entry aentry[] = table;
		if (obj != null) {
			int i = obj.hashCode();
			int j = (i & 0x7fffffff) % aentry.length;
			Entry entry2 = aentry[j];
			Entry entry3 = null;
			for (; entry2 != null; entry2 = entry2.next) {
				if (entry2.hash == i && entry2.key.equals(obj)) {
					if (entry3 != null) {
						entry3.next = entry2.next;
					} else {
						aentry[j] = entry2.next;
					}
					count--;
					return entry2.value;
				}
				entry3 = entry2;
			}

		} else {
			Entry entry = aentry[0];
			Entry entry1 = null;
			for (; entry != null; entry = entry.next) {
				if (entry.key == null) {
					if (entry1 != null) {
						entry1.next = entry.next;
					} else {
						aentry[0] = entry.next;
					}
					count--;
					return entry.value;
				}
				entry1 = entry;
			}

		}
		return null;
	}

	public void putAll(Map map) {
		java.util.Map.Entry entry;
		for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext(); put(
				entry.getKey(), entry.getValue())) {
			entry = (java.util.Map.Entry) iterator.next();
		}

	}

	public synchronized void clear() {
		table = new Entry[table.length];
		count = 0;
	}

	public Object clone() {
		try {
			ConHashMap conhashmap = (ConHashMap) super.clone();
			conhashmap.table = new Entry[table.length];
			for (int i = table.length; i-- > 0;) {
				conhashmap.table[i] = table[i] != null ? (Entry) table[i]
						.clone() : null;
			}

			conhashmap.keySet = null;
			conhashmap.entrySet = null;
			conhashmap.values = null;
			return conhashmap;
		} catch (CloneNotSupportedException clonenotsupportedexception) {
			throw new InternalError();
		}
	}

	public Set keySet() {
		if (keySet == null) {
			keySet = new _cls1();
		}
		return keySet;
	}

	public Collection values() {
		if (values == null) {
			values = new _cls2();
		}
		return values;
	}

	public Set entrySet() {
		if (entrySet == null) {
			entrySet = new _cls3();
		}
		return entrySet;
	}

	private synchronized void writeObject(ObjectOutputStream objectoutputstream)
			throws IOException {
		objectoutputstream.defaultWriteObject();
		objectoutputstream.writeInt(table.length);
		objectoutputstream.writeInt(count);
		for (int i = table.length - 1; i >= 0; i--) {
			for (Entry entry = table[i]; entry != null; entry = entry.next) {
				objectoutputstream.writeObject(entry.key);
				objectoutputstream.writeObject(entry.value);
			}

		}

	}

	private synchronized void readObject(ObjectInputStream objectinputstream)
			throws IOException, ClassNotFoundException {
		objectinputstream.defaultReadObject();
		int i = objectinputstream.readInt();
		table = new Entry[i];
		int j = objectinputstream.readInt();
		for (int k = 0; k < j; k++) {
			Object obj = objectinputstream.readObject();
			Object obj1 = objectinputstream.readObject();
			put(obj, obj1);
		}

	}

	int capacity() {
		return table.length;
	}

	float loadFactor() {
		return loadFactor;
	}

	public ConHashMap(int i, float f) {
		if (i < 0) {
			throw new IllegalArgumentException("Illegal Initial Capacity: " + i);
		}
		if (f > 1.0F || f <= 0.0F) {
			throw new IllegalArgumentException("Illegal Load factor: " + f);
		} else {
			loadFactor = f;
			table = new Entry[i];
			threshold = (int) ((float) i * f);
			return;
		}
	}

	public ConHashMap(int i) {
		this(i, 0.75F);
	}

	public ConHashMap() {
		this(101, 0.75F);
	}

	public ConHashMap(Map map) {
		this(Math.max(3 * map.size(), 11), 0.75F);
		putAll(map);
	}

	private class _cls1 extends AbstractSet {

		public Iterator iterator() {
			return new HashIterator(0);
		}

		public int size() {
			return count;
		}

		public boolean contains(Object obj) {
			return containsKey(obj);
		}

		public boolean remove(Object obj) {
			return ConHashMap.this.remove(obj) != null;
		}

		public void clear() {
			ConHashMap.this.clear();
		}

		private final void constructor$0(ConHashMap conhashmap) {
		  // nothing
		}

		_cls1() {
			constructor$0(ConHashMap.this);
		}
	}

	private class _cls2 extends AbstractCollection {

		public Iterator iterator() {
			return new HashIterator(1);
		}

		public int size() {
			return count;
		}

		public boolean contains(Object obj) {
			return containsValue(obj);
		}

		public void clear() {
			ConHashMap.this.clear();
		}

		private final void constructor$0(ConHashMap conhashmap) {
		  // nothing
		}

		_cls2() {
			constructor$0(ConHashMap.this);
		}
	}

	private class _cls3 extends AbstractSet {

		public Iterator iterator() {
			return new HashIterator(2);
		}

		public boolean contains(Object obj) {
			if (!(obj instanceof java.util.Map.Entry)) {
				return false;
			}
			java.util.Map.Entry entry = (java.util.Map.Entry) obj;
			Object obj1 = entry.getKey();
			ConHashMap.Entry aentry[] = table;
			int i = obj1 == null ? 0 : obj1.hashCode();
			int j = (i & 0x7fffffff) % aentry.length;
			for (ConHashMap.Entry entry1 = aentry[j]; entry1 != null; entry1 = entry1.next) {
				if (entry1.hash == i && entry1.equals(entry)) {
					return true;
				}
			}

			return false;
		}

		public boolean remove(Object obj) {
			if (!(obj instanceof java.util.Map.Entry)) {
				return false;
			}
			java.util.Map.Entry entry = (java.util.Map.Entry) obj;
			Object obj1 = entry.getKey();
			synchronized (ConHashMap.this) {
				ConHashMap.Entry aentry[] = table;
				int i = obj1 == null ? 0 : obj1.hashCode();
				int j = (i & 0x7fffffff) % aentry.length;
				ConHashMap.Entry entry1 = aentry[j];
				ConHashMap.Entry entry2 = null;
				for (; entry1 != null; entry1 = entry1.next) {
					if (entry1.hash == i && entry1.equals(entry)) {
						if (entry2 != null) {
							entry2.next = entry1.next;
						} else {
							aentry[j] = entry1.next;
						}
						count--;
						entry1.value = null;
						boolean flag = true;
						return flag;
					}
					entry2 = entry1;
				}

				boolean flag1 = false;
				return flag1;
			}
		}

		public int size() {
			return count;
		}

		public void clear() {
			ConHashMap.this.clear();
		}

		private final void constructor$0(ConHashMap conhashmap) {
		  // nothing
		}

		_cls3() {
			constructor$0(ConHashMap.this);
		}
	}

}
